<template>
  <div
    class="cg-switch"
    :class="{ 'is-disabled': switchDisabled, 'is-checked': checked }"
    role="switch"
    :aria-checked="checked"
    :aria-disabled="switchDisabled"
    @click.prevent="switchValue"
  >
    <input
      class="cg-switch-input"
      type="checkbox"
      @change="handleChange"
      ref="input"
      :true-value="activeValue"
      :false-value="inactiveValue"
      :disabled="switchDisabled"
    />
    <span class="cg-switch-core" ref="core" :style="{ width: coreWidth + 'px' }">
      <span class="cg-switch-stone" :style="boxStyle"></span>
    </span>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import Color from 'color'

// 定义组件名称
// 注意：defineOptions 是 Vue 3.3+ 的实验性特性
// 如果遇到兼容性问题，可以删除此部分或使用插件支持
// 组件名称通常不是必须的，除非用于递归组件或调试
defineOptions({
  name: 'cg-switch'
})

// 定义props
const props = defineProps<{
  color: string
  modelValue: boolean | string | number
  activeValue: boolean | string | number
  inactiveValue: boolean | string | number
  disabled: boolean
  width: number
}>()

// 定义emits
const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean | string | number): void
  (e: 'input', value: boolean | string | number): void
  (e: 'change', value: boolean | string | number): void
}>()

// 响应式数据
const coreWidth = ref(props.width)

// 组件引用
const input = ref<HTMLInputElement | null>(null)
const core = ref<HTMLSpanElement | null>(null)

// 计算属性
const checked = computed(() => {
  return props.modelValue === props.activeValue
})

const switchDisabled = computed(() => {
  return props.disabled
})

const boxStyle = computed(() => {
  const color = Color(props.color)

  if (!checked.value) {
    return {}
  }

  if (switchDisabled.value) {
    const bgColor = color.mix(Color('#fff'), 0.5)
    return {
      color: '#fff',
      background: bgColor.hex(),
      border: '1px solid ' + bgColor.hex()
    }
  }

  let colors = []
  for (let num = 1; num < 5; num++) {
    colors.push(color.lighten(Math.max(0.2 - 0.05 * num, 0)))
  }
  let rColors = [...colors].reverse()
  colors.push(color)
  colors = colors.concat(rColors)
  let textColor = colors.map((c) => c.hex()).join(',')
  return {
    color: '#FFFFFF',
    background: `linear-gradient(0deg,${textColor})`
  }
})

// 监听
watch(checked, (newVal) => {
  if (input.value) {
    input.value.checked = newVal
  }
})

// 生命周期
onMounted(() => {
  coreWidth.value = props.width || 40
  if (input.value) {
    input.value.checked = checked.value
  }
})

// 方法
const switchValue = () => {
  if (!switchDisabled.value) {
    handleChange()
  }
}

const handleChange = () => {
  const val = checked.value ? props.inactiveValue : props.activeValue
  console.log('handleChange', val)
  emit('update:modelValue', val)
  emit('input', val)
  emit('change', val)
  nextTick(() => {
    if (input.value) {
      input.value.checked = checked.value
    }
  })
}
</script>

<style lang="scss">
@use './style.scss';
</style>
